Skip to main content

Functions

1. Function Declaration

Functions are defined using the def keyword followed by the function name and parentheses with a colon ():. The code that belongs to the function must be indented with whitespace. Functions cannot be empty.

def greet():
print("Hello, world!")

In Python, functions need to be defined before they are called. The interpreter executes code from top to bottom, so you must define a function before you can use it.

greet()  # This will raise a NameError

def greet():
print("Hello!")

After defining a function, you can use the function by calling it.

def greet():
print("Hello!")

greet() # This works

2. Parameters

  • A function can be defined with parameters in between the parentheses (). The parameters are separated by commas in the function definition.
  • When calling a function, you can pass values, variables, or expressions as arguments to the function.

Example: In this example, we defined a function called greet that takes a parameter called name. We call the function by passing in "Alice" as the argument.

def greet(name):
msg = "Hello, " + name
print(msg)

greet("Alice") # This will print "Hello, Alice"

3. Return Statements

The return value from a functiom allows you to use the result of a function in other parts of your code, outside of the original function.

def add(x, y):
return x + y

result = add(3, 5)
print(result) # This will print 8

4. Type Hints

In Python, you can add type hints to your functions to indicate what type of data the function expects to receive and return. This is not required, but it can be helpful for other developers who are reading your code.

  • To add a type hint for a parameter, you add a colon after the parameter name and then the type of data you expect.
  • To add a return type, you add a right arrow (->) after the closing parenthesis and then the type of data you expect to return (before the colon).
def add(x: int, y: int) -> int:
return x + y

Type hints don't change how the function works, for example, we could still pass a couple of strings to the add function above and it would still work.

When we have a function that doesn’t return anything, the return type would be None.

def greet(name: str) -> None:
print("Hello, " + name)

5. Scope

The scope refers to the visibility or accessibility of variables within different parts of the code. Python uses the LEGB rule for scope resolution. It searches for variables in the following order:

  • Local (L)
  • Enclosing (E)
  • Global (G)
  • Built-in (B)

1. Local Scope

  • Variables declared within a function have a local scope.
  • They can only be accessed within the function in which they are defined.
  • Local variables are created when the function is called and destroyed when the function exits.
def declare_variable() -> None:
inside_function_only = 10
return

declare_variable()
print(inside_function_only) # This will raise a NameError

2. Enclosing Scope

  • Relevant for nested functions
  • Outer function's scope is accessible to inner functions
  • The nonlocal keyword is used to work with variables inside nested functions

3. Global Scope

  • Variables declared outside of any function have a global scope.
  • They can be accessed from anywhere in the program, including inside functions.
  • The global keyword allows modification of global variables from within functions
n = 10

def print_global_variable() -> None:
print(n)

print_global_variable() # This will print 10

4. Built-in Scope

  • Python's pre-defined functions and keywords
**Example: **
x = "global"  # variable in the global scope

def func():
x = "local" # variable x in func's local scope

def inner1():
nonlocal x # Use the x from the enclosing scope (func)
x = "nonlocal"

def inner2():
global x # Use the x from the global scope
x = "global changed"

print("Before:", x) # Print func's local x

inner1() # Call inner1, which modifies func's x
print("After nonlocal:", x) # Print func's x after inner1

inner2() # Call inner2, which modifies global x
print("After global:", x) # Print func's x (unchanged by inner2)

print("Global before:", x) # Print global x before calling func
func() # Call func
print("Global after:", x) # Print global x after func (changed by inner2)
Global before: global
Before: local
After nonlocal: nonlocal
After global: nonlocal
Global after: global changed

6. Default Arguments

You can specify default values for parameters in a function definition.

  • If we call the function without any arguments, the default value will be used.
  • If we call the function with an argument, that argument will be used instead.
def greet(name="world"):
print("Hello, " + name + "!")

greet() # This will print "Hello, world!"
greet("Bob") # This will print "Hello, Bob!"

We can also have multiple parameters with default values. Parameters with default values must come after parameters without default values.

# This is valid
def greet(greeting="Hello", name="world"):
print(greeting + ", " + name + "!")

# This is valid
def greet(greeting, name="world"):
print(greeting + ", " + name + "!")

# This is NOT valid
def greet(greeting="Hello", name):
print(greeting + ", " + name + "!")